/********************************************************************************/
/*										*/
/*		This file is a collection of miscellaneous macros.     		*/
/*			     Written by Ken Goldman				*/
/*		       IBM Thomas J. Watson Research Center			*/
/*            $Id: GpMacros.h 1529 2019-11-21 23:29:01Z kgoldman $		*/
/*										*/
/*  Licenses and Notices							*/
/*										*/
/*  1. Copyright Licenses:							*/
/*										*/
/*  - Trusted Computing Group (TCG) grants to the user of the source code in	*/
/*    this specification (the "Source Code") a worldwide, irrevocable, 		*/
/*    nonexclusive, royalty free, copyright license to reproduce, create 	*/
/*    derivative works, distribute, display and perform the Source Code and	*/
/*    derivative works thereof, and to grant others the rights granted herein.	*/
/*										*/
/*  - The TCG grants to the user of the other parts of the specification 	*/
/*    (other than the Source Code) the rights to reproduce, distribute, 	*/
/*    display, and perform the specification solely for the purpose of 		*/
/*    developing products based on such documents.				*/
/*										*/
/*  2. Source Code Distribution Conditions:					*/
/*										*/
/*  - Redistributions of Source Code must retain the above copyright licenses, 	*/
/*    this list of conditions and the following disclaimers.			*/
/*										*/
/*  - Redistributions in binary form must reproduce the above copyright 	*/
/*    licenses, this list of conditions	and the following disclaimers in the 	*/
/*    documentation and/or other materials provided with the distribution.	*/
/*										*/
/*  3. Disclaimers:								*/
/*										*/
/*  - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF	*/
/*  LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH	*/
/*  RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES)	*/
/*  THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE.		*/
/*  Contact TCG Administration (admin@trustedcomputinggroup.org) for 		*/
/*  information on specification licensing rights available through TCG 	*/
/*  membership agreements.							*/
/*										*/
/*  - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED 	*/
/*    WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR 	*/
/*    FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR 		*/
/*    NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY 		*/
/*    OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE.		*/
/*										*/
/*  - Without limitation, TCG and its members and licensors disclaim all 	*/
/*    liability, including liability for infringement of any proprietary 	*/
/*    rights, relating to use of information in this specification and to the	*/
/*    implementation of this specification, and TCG disclaims all liability for	*/
/*    cost of procurement of substitute goods or services, lost profits, loss 	*/
/*    of use, loss of data or any incidental, consequential, direct, indirect, 	*/
/*    or special damages, whether under contract, tort, warranty or otherwise, 	*/
/*    arising in any way out of use or reliance upon this specification or any 	*/
/*    information herein.							*/
/*										*/
/*  (c) Copyright IBM Corp. and others, 2016 - 2019				*/
/*										*/
/********************************************************************************/

#ifndef GPMACROS_H
#define GPMACROS_H


#define  USE_BIT_FIELD_STRUCTURES    0  


/* 5.9.16.8	From TPMFail.c */

/* This value holds the address of the string containing the name of the function in which the
   failure occurred. This address value isn't useful for anything other than helping the vendor to
   know in which file the failure occurred. */
int      g_inFailureMode;       // Indicates that the TPM is in failure mode
#if SIMULATION
int      g_forceFailureMode;    // flag to force failure mode during test
#endif
typedef void(FailFunction)(const char *function, int line, int code);
#if defined TPM_FAIL_C || defined GLOBAL_C || 1
UINT32    s_failFunction;
UINT32    s_failLine;            // the line in the file at which
// the error was signaled
UINT32    s_failCode;            // the error code used
FailFunction    *LibFailCallback;
#endif // TPM_FAIL_C


/* 9.2.3 Functions */
/* 9.2.3.1 TestBit() */
/* This function is used to check the setting of a bit in an array of bits. */
/* Return Values Meaning */
/* TRUE bit is set */
/* FALSE bit is not set */

int
TestBit(
	unsigned int     bitNum,        // IN: number of the bit in 'bArray'
	BYTE            *bArray,        // IN: array containing the bits
	unsigned int     bytesInArray   // IN: size in bytes of 'bArray'
	)
{
    // pAssert(bytesInArray > (bitNum >> 3));
    return((bArray[bitNum >> 3] & (1 << (bitNum & 7))) != 0);
}

/* 9.2.3.2 SetBit() */
/* This function will set the indicated bit in bArray. */

void
SetBit(
       unsigned int     bitNum,        // IN: number of the bit in 'bArray'
       BYTE            *bArray,        // IN: array containing the bits
       unsigned int     bytesInArray   // IN: size in bytes of 'bArray'
       )
{
    // pAssert(bytesInArray > (bitNum >> 3));
    bArray[bitNum >> 3] |= (1 << (bitNum & 7));
}

/* 9.2.3.3 ClearBit() */
/* This function will clear the indicated bit in bArray. */

void
ClearBit(
	 unsigned int     bitNum,        // IN: number of the bit in 'bArray'.
	 BYTE            *bArray,        // IN: array containing the bits
	 unsigned int     bytesInArray   // IN: size in bytes of 'bArray'
	 )
{
    // pAssert(bytesInArray > (bitNum >> 3));
    bArray[bitNum >> 3] &= ~(1 << (bitNum & 7));
}

/* These are defined for use when the size of the vector being checked is known at compile time. */
#define TEST_BIT(bit, vector)   TestBit((bit), (BYTE *)&(vector), sizeof(vector))
#define SET_BIT(bit, vector)    SetBit((bit), (BYTE *)&(vector), sizeof(vector))
#define CLEAR_BIT(bit, vector) ClearBit((bit), (BYTE *)&(vector), sizeof(vector))

/* 5.10.1	Introduction */
/* This file is a collection of miscellaneous macros. */
#ifndef NULL
#define NULL 0
#endif

// #include "swap.h"
// #include "VendorString.h"

/* 10.1.7 CryptTest.h */
/* This file contains constant definitions used for self test */
/* This is the definition of a bit array with one bit per algorithm */
/* NOTE: Since bit numbering starts at zero, when ALG_LAST_VALUE is a multiple of 8,
   ALGORITHM_VECTOR will need to have byte for the single bit in the last byte. So, for example,
   when ALG_LAST_VECTOR is 8, ALGORITHM_VECTOR will need 2 bytes. */
#define ALGORITHM_VECTOR_BYTES  ((ALG_LAST_VALUE + 8) / 8)
typedef BYTE    ALGORITHM_VECTOR[ALGORITHM_VECTOR_BYTES];

/* 5.9.10	RAM Global Values */
/* 5.9.10.1	Description */
/* The values in this section are only extant in RAM or ROM as constant values. */
/* 5.9.10.2	Crypto Self-Test Values */
ALGORITHM_VECTOR     g_implementedAlgorithms;
ALGORITHM_VECTOR     g_toTest;

/* 10.2.1.6.4 TestAlgorithm() */
/* Dispatches to the correct test function for the algorithm or gets a list of testable
   algorithms. */
/* If toTest is not NULL, then the test decisions are based on the algorithm selections in
   toTest. Otherwise, g_toTest is used. When bits are clear in g_toTest they will also be cleared
   toTest. */
/* If there doesn't happen to be a test for the algorithm, its associated bit is quietly cleared. */
/* If alg is zero (TPM_ALG_ERROR), then the toTest vector is cleared of any bits for which there is
   no test (i.e. no tests are actually run but the vector is cleared). */
/* NOTE: toTest will only ever have bits set for implemented algorithms but alg can be anything. */
/* Error Returns Meaning */
/* TPM_RC_CANCELED test was canceled */
    // TODO: TestAlgorithm 注释
/* TPM_RC
TestAlgorithm(
	      TPM_ALG_ID               alg,
	      ALGORITHM_VECTOR        *toTest
	      )
{
    TPM_ALG_ID              first = (alg == ALG_ERROR_VALUE) ? ALG_FIRST_VALUE : alg;
    TPM_ALG_ID              last = (alg == ALG_ERROR_VALUE) ? ALG_LAST_VALUE : alg;
    int                    doTest = (alg != ALG_ERROR_VALUE);
    TPM_RC                  result = TPM_RC_SUCCESS;
    if(toTest == NULL)
	toTest = &g_toTest;
    // This is kind of strange. This function will either run a test of the selected
    // algorithm or just clear a bit if there is no test for the algorithm. So,
    // either this loop will be executed once for the selected algorithm or once for
    // each of the possible algorithms. If it is executed more than once ('alg' ==
    // TPM_ALG_ERROR), then no test will be run but bits will be cleared for
    // unimplemented algorithms. This was done this way so that there is only one
    // case statement with all of the algorithms. It was easier to have one case
    // statement than to have multiple ones to manage whenever an algorithm ID is
    // added.
    for(alg = first; (alg <= last); alg++)
	{
	    // if 'alg' was TPM_ALG_ERROR, then we will be cycling through
	    // values, some of which may not be implemented. If the bit in toTest
	    // happens to be set, then we could either generated an assert, or just
	    // silently CLEAR it. Decided to just clear.
	    if(!TEST_BIT(alg, g_implementedAlgorithms))
		{
		    CLEAR_BIT(alg, *toTest);
		    continue;
		}
	    // Process whatever is left.
	    // NOTE: since this switch will only be called if the algorithm is
	    // implemented, it is not necessary to modify this list except to comment
	    // out the algorithms for which there is no test
	    switch(alg)
		{
		    // Symmetric block ciphers
#if ALG_AES
		  case ALG_AES_VALUE:
#endif
#if ALG_SM4
		    // if SM4 is implemented, its test is like other block ciphers but there
		    // aren't any test vectors for it yet
		    //            case ALG_SM4_VALUE:
#endif
// #if !ALG_HMAC
// #   error   HMAC is required in all TPM implementations
// #endif
// 		  case ALG_HMAC_VALUE:
// 		    // Clear the bit that indicates that HMAC is required because
// 		    // HMAC is used as the basic test for all hash algorithms.
// 		    CLEAR_BOTH(alg);
// 		    // Testing HMAC means test the default hash
// 		    if(doTest)
// 			TestHash(DEFAULT_TEST_HASH, toTest);
// 		    else
// 			// If not testing, then indicate that the hash needs to be
// 			// tested because this uses HMAC
// 			SET_BOTH(DEFAULT_TEST_HASH);
// 		    break;
// 		    // if SM3 is implemented its test is like any other hash, but there
// 		    // aren't any test vectors yet.
// #if ALG_SM3_256
// 		               case ALG_SM3_256_VALUE:
// #endif // TPM_ALG_SM3_256
// #if ALG_ECC
// 		    // ECC dependent but no tests
// 		    //        case ALG_ECDAA_VALUE:
// 		    //        case ALG_ECMQV_VALUE:
// 		    //        case ALG_KDF1_SP800_56a_VALUE:
// 		    //        case ALG_KDF2_VALUE:
// 		    //        case ALG_MGF1_VALUE:
// 		  case ALG_ECC_VALUE:
// 		    CLEAR_BOTH(alg);
// 		    if(doTest)
// 			result = TestEcc(ALG_ECDH_VALUE, toTest);
// 		    else
// 			SET_BOTH(ALG_ECDH_VALUE);
// 		    break;
// 		  case ALG_ECDSA_VALUE:
// 		  case ALG_ECDH_VALUE:
// 		  case ALG_ECSCHNORR_VALUE:
// 		    //            case ALG_SM2_VALUE:
// 		    if(doTest)
// 			result = TestEcc(alg, toTest);
// 		    break;
// #endif // ALG_ECC_VALUE
		  default:
		    CLEAR_BIT(alg, *toTest);
		    break;
		}
	    if(result != TPM_RC_SUCCESS)
		break;
	}
    return result;
} */
/* 10.2.7.2.5 CryptTestAlgorithm() */
/* Only point of contact with the actual self tests. If a self-test fails, there is no return and
   the TPM goes into failure mode. The call to TestAlgorithm() uses an algorithm selector and a bit
   vector. When the test is run, the corresponding bit in toTest and in g_toTest is CLEAR. If toTest
   is NULL, then only the bit in g_toTest is CLEAR. There is a special case for the call to
   TestAlgorithm(). When alg is TPM_ALG_ERROR, TestAlgorithm() will CLEAR any bit in toTest for
   which it has no test. This allows the knowledge about which algorithms have test to be accessed
   through the interface that provides the test. */
/* Error Returns Meaning */
/* TPM_RC_CANCELED test was canceled */
/* TPM_RC
CryptTestAlgorithm(
    TPM_ALG_ID alg,
    ALGORITHM_VECTOR *toTest)
{
    TPM_RC result;
#if SELF_TEST
    result = TestAlgorithm(alg, toTest);
#else
    // If this is an attempt to determine the algorithms for which there is a
    // self test, pretend that all of them do. We do that by not clearing any
    // of the algorithm bits. When/if this function is called to run tests, it
    // will over report. This can be changed so that any call to check on which
    // algorithms have tests, 'toTest' can be cleared.
    if (alg != TPM_ALG_ERROR)
    {
        CLEAR_BIT(alg, g_toTest);
        if (toTest != NULL)
            CLEAR_BIT(alg, *toTest);
    }
    result = TPM_RC_SUCCESS;
#endif
    return result;
} */

/* 5.10.2	For Self-test */
/* These macros are used in CryptUtil() to invoke the incremental self test. */
#if SELF_TEST
#   define     TEST(alg) if(TEST_BIT(alg, g_toTest)) CryptTestAlgorithm(alg, NULL)
/* Use of TPM_ALG_NULL is reserved for RSAEP/RSADP testing. If someone is wanting to test a hash
   with that value, don't do it. */
#   define     TEST_HASH(alg)						\
    if(TEST_BIT(alg, g_toTest)						\
       &&  (alg != ALG_NULL_VALUE))					\
	CryptTestAlgorithm(alg, NULL)
#else
#   define TEST(alg)
#   define TEST_HASH(alg)
#endif // SELF_TEST

/* 9.17.4.2 TpmFail() */
/* This function is called by TPM.lib when a failure occurs. It will set up the failure values to be
   returned on TPM2_GetTestResult(). */
void TpmFail(
#if FAIL_TRACE
    const char *function,
    int line,
#endif
    int code)
{
    // Save the values that indicate where the error occurred.
    // On a 64-bit machine, this may truncate the address of the string
    // of the function name where the error occurred.
#if FAIL_TRACE
    Memcpy(&s_failFunction, function, sizeof(UINT32));
    s_failLine = line;
#else
    s_failFunction = (UINT32)NULL;
    s_failLine = 0;
#endif
    s_failCode = code;
    // We are in failure mode
    g_inFailureMode = TRUE;
    // if asserts are enabled, then do an assert unless the failure mode code
    // is being tested.
#if SIMULATION
#ifndef NDEBUG
    // assert(g_forceFailureMode);
#endif
    // Clear this flag
    g_forceFailureMode = FALSE;
#endif
    // Jump to the failure mode code.
    // Note: only get here if asserts are off or if we are testing failure mode
    // _plat__Fail();
}

/* 5.10.3	For Failures */
#if defined _POSIX_
#   define FUNCTION_NAME        0
#else
#   define FUNCTION_NAME        __FUNCTION__
#endif
#if !FAIL_TRACE
#   define FAIL(errorCode) (TpmFail(errorCode))
#   define LOG_FAILURE(errorCode) (TpmLogFailure(errorCode))
#else
#   define FAIL(errorCode)        TpmFail(FUNCTION_NAME, __LINE__, errorCode)
// #   define LOG_FAILURE(errorCode) TpmLogFailure(FUNCTION_NAME, __LINE__, errorCode)
#endif
/* If implementation is using longjmp, then the call to TpmFail() does not return and the compiler
   will complain about unreachable code that comes after. To allow for not having longjmp, TpmFail()
   will return and the subsequent code will be executed. This macro accounts for the difference. */
#ifndef NO_LONGJMP
#   define FAIL_RETURN(returnCode)
#   define TPM_FAIL_RETURN     NORETURN void
#else
#   define FAIL_RETURN(returnCode) return (returnCode)
#   define TPM_FAIL_RETURN     void
#endif
/* This macro tests that a condition is TRUE and puts the TPM into failure mode if it is not. If
   longjmp is being used, then the FAIL(FATAL_ERROR_) macro makes a call from which there is no
   return. Otherwise, it returns and the function will exit with the appropriate return code. */
#define REQUIRE(condition, errorCode, returnCode)		\
    {								\
	if(!!(condition))					\
	    {							\
		FAIL(FATAL_ERROR_errorCode);			\
		FAIL_RETURN(returnCode);			\
	    }							\
    }
#define PARAMETER_CHECK(condition, returnCode)		\
    REQUIRE((condition), PARAMETER, returnCode)
#if defined EMPTY_ASSERT && (EMPTY_ASSERT != NO)
#   define pAssert(a)  ((void)0)
#else
#   define pAssert(a) {if(!(a)) FAIL(FATAL_ERROR_PARAMETER);}
#endif
/* 5.10.4	Derived from Vendor-specific values */
/* Values derived from vendor specific settings in TpmProfile.h */
#define PCR_SELECT_MIN          ((PLATFORM_PCR+7)/8)
#define PCR_SELECT_MAX          ((IMPLEMENTATION_PCR+7)/8)
#define MAX_ORDERLY_COUNT       ((1 << ORDERLY_BITS) - 1)
#define RSA_MAX_PRIME           (MAX_RSA_KEY_BYTES / 2)
#define RSA_PRIVATE_SIZE        (RSA_MAX_PRIME * 5)

/* 5.10.5	Compile-time Checks */
/* In some cases, the relationship between two values may be dependent on things that change based
   on various selections like the chosen cryptographic libraries. It is possible that these
   selections will result in incompatible settings. These are often detectable by the compiler but
   it isn't always possible to do the check in the preprocessor code. For example, when the check
   requires use of sizeof then the preprocessor can't do the comparison. For these cases, we include
   a special macro that, depending on the compiler will generate a warning to indicate if the check
   always passes or always fails because it involves fixed constants. To run these checks, define
   COMPILER_CHECKS in TpmBuildSwitches.h */
#if COMPILER_CHECKS
#   define  cAssert     pAssert
#else
#   define cAssert(value)
#endif
/* This is used commonly in the Crypt code as a way to keep listings from getting too long. This is
   not to save paper but to allow one to see more useful stuff on the screen at any given time. */
#define     ERROR_RETURN(returnCode)		\
    {						\
	retVal = returnCode;			\
	goto Exit;				\
    }
#ifndef MAX
#  define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef MIN
#  define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
#ifndef IsOdd
#  define IsOdd(a)        (((a) & 1) != 0)
#endif
#ifndef BITS_TO_BYTES
#  define BITS_TO_BYTES(bits) (((bits) + 7) >> 3)
#endif
#ifndef DIV_UP
#  define DIV_UP(var, div) ((var + div - 1) / (div))
#endif

/* The following definitions are used if they have not already been defined. The defaults for these
   settings are compatible with ISO/IEC 9899:2011 (E) */
#ifndef LIB_EXPORT
#   define LIB_EXPORT
#   define LIB_IMPORT
#endif
#ifndef NORETURN
#   define NORETURN _Noreturn
#endif
// #ifndef NOT_REFERENCED
// #   define NOT_REFERENCED(x = x)   ((void) (x))
// #endif
#define STD_RESPONSE_HEADER (sizeof(TPM_ST) + sizeof(UINT32) + sizeof(TPM_RC))
#define JOIN(x,y) x##y
#define JOIN3(x, y, z) x##y##z
#define CONCAT(x,y) JOIN(x, y)
#define CONCAT3(x, y, z) JOIN3(x,y,z)
/*     If CONTEXT_INTEGRITY_HASH_ALG is defined, then the vendor is using the old style
       table. Otherwise, pick the strongest implemented hash algorithm as the context hash. */
#ifndef CONTEXT_HASH_ALGORITHM
#   if defined ALG_SHA512 && ALG_SHA512 == YES
#       define CONTEXT_HASH_ALGORITHM    SHA512
#   elif defined ALG_SHA384 && ALG_SHA384 == YES
#       define CONTEXT_HASH_ALGORITHM    SHA384
#   elif defined ALG_SHA256 && ALG_SHA256 == YES
#       define CONTEXT_HASH_ALGORITHM    SHA256
#   elif defined ALG_SM3_256 && ALG_SM3_256 == YES
#       define CONTEXT_HASH_ALGORITHM    SM3_256
#   elif defined ALG_SHA1 && ALG_SHA1 == YES
#       define CONTEXT_HASH_ALGORITHM  SHA1
#   endif
#   define CONTEXT_INTEGRITY_HASH_ALG  CONCAT(TPM_ALG_, CONTEXT_HASH_ALGORITHM)
#endif
#ifndef CONTEXT_INTEGRITY_HASH_SIZE
#define CONTEXT_INTEGRITY_HASH_SIZE CONCAT(CONTEXT_HASH_ALGORITHM, _DIGEST_SIZE)
#endif
#if ALG_RSA
#define     RSA_SECURITY_STRENGTH (MAX_RSA_KEY_BITS >= 15360 ? 256 :	\
				  (MAX_RSA_KEY_BITS >=  7680 ? 192 :	\
				  (MAX_RSA_KEY_BITS >=  3072 ? 128 :	\
				  (MAX_RSA_KEY_BITS >=  2048 ? 112 :    \
				  (MAX_RSA_KEY_BITS >=  1024 ?  80 :  0)))))
#else
#define     RSA_SECURITY_STRENGTH   0
#endif // ALG_RSA
#if ALG_ECC
#define     ECC_SECURITY_STRENGTH (MAX_ECC_KEY_BITS >= 521 ? 256 :	\
				  (MAX_ECC_KEY_BITS >= 384 ? 192 :	\
				  (MAX_ECC_KEY_BITS >= 256 ? 128 : 0)))
#else
#define     ECC_SECURITY_STRENGTH   0
#endif // ALG_ECC
#define     MAX_ASYM_SECURITY_STRENGTH					\
    MAX(RSA_SECURITY_STRENGTH, ECC_SECURITY_STRENGTH)
#define     MAX_HASH_SECURITY_STRENGTH  ((CONTEXT_INTEGRITY_HASH_SIZE * 8) / 2)

/*     Unless some algorithm is broken... */

#define     MAX_SYM_SECURITY_STRENGTH   MAX_SYM_KEY_BITS
#define MAX_SECURITY_STRENGTH_BITS					\
    MAX(MAX_ASYM_SECURITY_STRENGTH,					\
	MAX(MAX_SYM_SECURITY_STRENGTH,					\
	    MAX_HASH_SECURITY_STRENGTH))
/*     This is the size that was used before the 1.38 errata requiring that P1.14.4 be followed */
#define PROOF_SIZE      CONTEXT_INTEGRITY_HASH_SIZE
/*     As required by P1.14.4 */
#define COMPLIANT_PROOF_SIZE						\
    (MAX(CONTEXT_INTEGRITY_HASH_SIZE, (2 * MAX_SYM_KEY_BYTES)))
/*     As required by P1.14.3.1 */
#define COMPLIANT_PRIMARY_SEED_SIZE				\
    BITS_TO_BYTES(MAX_SECURITY_STRENGTH_BITS * 2)
/*     This is the pre-errata version */
#ifndef PRIMARY_SEED_SIZE
#   define PRIMARY_SEED_SIZE    PROOF_SIZE
#endif
#if USE_SPEC_COMPLIANT_PROOFS
#   undef PROOF_SIZE
#   define PROOF_SIZE           COMPLIANT_PROOF_SIZE
#   undef PRIMARY_SEED_SIZE
#   define PRIMARY_SEED_SIZE    COMPLIANT_PRIMARY_SEED_SIZE
#endif  // USE_SPEC_COMPLIANT_PROOFS
#if !SKIP_PROOF_ERRORS
#   if PROOF_SIZE < COMPLIANT_PROOF_SIZE
#       error "PROOF_SIZE is not compliant with TPM specification"
#   endif
#   if PRIMARY_SEED_SIZE < COMPLIANT_PRIMARY_SEED_SIZE
#       error  "Non-compliant PRIMARY_SEED_SIZE"
#   endif
#endif	// !SKIP_PROOF_ERRORS

/* If CONTEXT_ENCRYPT_ALG is defined, then the vendor is using the old style table */
#if defined CONTEXT_ENCRYPT_ALG
#   undef CONTEXT_ENCRYPT_ALGORITHM
#   if CONTEXT_ENCRYPT_ALG == ALG_AES_VALUE
#       define CONTEXT_ENCRYPT_ALGORITHM  AES
#   elif CONTEXT_ENCRYPT_ALG == ALG_SM4_VALUE
#       define CONTEXT_ENCRYPT_ALGORITHM  SM4
#   elif CONTEXT_ENCRYPT_ALG == ALG_CAMELLIA_VALUE
#       define CONTEXT_ENCRYPT_ALGORITHM  CAMELLIA
#   elif CONTEXT_ENCRYPT_ALG == ALG_TDES_VALUE
#   error Are you kidding?
#   else
#       error Unknown value for CONTEXT_ENCRYPT_ALG
#   endif // CONTEXT_ENCRYPT_ALG == ALG_AES_VALUE
#else
#   define CONTEXT_ENCRYPT_ALG						\
    CONCAT3(ALG_, CONTEXT_ENCRYPT_ALGORITHM, _VALUE)
#endif  // CONTEXT_ENCRYPT_ALG
#define CONTEXT_ENCRYPT_KEY_BITS					\
    CONCAT(CONTEXT_ENCRYPT_ALGORITHM, _MAX_KEY_SIZE_BITS)
#define CONTEXT_ENCRYPT_KEY_BYTES       ((CONTEXT_ENCRYPT_KEY_BITS+7)/8)

/* This is updated to follow the requirement of P2 that the label not be larger than 32 bytes. */
#ifndef LABEL_MAX_BUFFER
#define LABEL_MAX_BUFFER MIN(32, MAX(MAX_ECC_KEY_BYTES, MAX_DIGEST_SIZE))
#endif
/* This bit is used to indicate that an authorization ticket expires on TPM Reset and TPM Restart.It
   is added to the timeout value returned by TPM2_PoliySigned() and TPM2_PolicySecret() and used by
   TPM2_PolicyTicket(). The timeout value is relative to Time (g_time). Time is reset whenever the
   TPM loses power and cannot be moved forward by the user (as can Clock). g_time is a 64-bit value
   expressing time in ms. Stealing the MSb() for a flag means that the TPM needs to be reset at least
   once every 292,471,208 years rather than once every 584,942,417 years. */
#define EXPIRATION_BIT ((UINT64)1 << 63)
/* Check for consistency of the bit ordering of bit fields */
#if BIG_ENDIAN_TPM && MOST_SIGNIFICANT_BIT_0 && USE_BIT_FIELD_STRUCTURES
#   error "Settings not consistent"
#endif
/* These macros are used to handle the variation in handling of bit fields. If */
#if USE_BIT_FIELD_STRUCTURES // The default, old version, with bit fields
#   define IS_ATTRIBUTE(a, type, b)        ((a.b) != 0)
#   define SET_ATTRIBUTE(a, type, b)       (a.b = SET)
#   define CLEAR_ATTRIBUTE(a, type, b)     (a.b = CLEAR)
#   define GET_ATTRIBUTE(a, type, b)       (a.b)
#   define TPMA_ZERO_INITIALIZER()          {0}
#else
#   define IS_ATTRIBUTE(a, type, b)        ((a & type##_##b) != 0)
#   define SET_ATTRIBUTE(a, type, b)       (a |= type##_##b)
#   define CLEAR_ATTRIBUTE(a, type, b)     (a &= ~type##_##b)
#   define GET_ATTRIBUTE(a, type, b)					\
    (type)((a & type##_##b) >> type##_##b##_SHIFT)
#   define TPMA_ZERO_INITIALIZER()         (0)
#endif
#define VERIFY(_X) if(!(_X)) goto Error
// These macros determine if the values in this file are referenced or instanced.
// Global.c defines GLOBAL_C so all the values in this file will be instanced in
// Global.obj. For all other files that include this file, the values will simply
// be external references. For constants, there can be an initializer.

// #ifdef GLOBAL_C
#define EXTERN  extern
#define INITIALIZER(_value_)  = _value_
// #else
// #define EXTERN  extern
// #define INITIALIZER(_value_)
// #endif

// This macro will create an OID. All OIDs are in DER form with a first octet of
// 0x06 indicating an OID fallowed by an octet indicating the number of octets in the
// rest of the OID. This allows a user of this OID to know how much/little to copy.
#define MAKE_OID(NAME)							\
    EXTERN  const BYTE OID##NAME[] INITIALIZER({OID##NAME##_VALUE})

/* This definition is moved from TpmProfile.h because it is not actually vendor- specific. It has to
   be the same size as the sequence parameter of a TPMS_CONTEXT and that is a UINT64. So, this is an
   invariant value */
#define CONTEXT_COUNTER         UINT64

#endif // GP_MACROS_H
